package com.xuzm.system.utils;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 环形集合，当集合满后添加会覆盖最旧的数据
 */
public class CircularBuffer<T> {
    private final T[] buffer;
    private int tail;
    private final AtomicInteger  maxIndex = new AtomicInteger(0);
    private final int size;
    private final ReentrantReadWriteLock lock;
    private final Condition notEmpty;

    @SuppressWarnings("unchecked")
    public CircularBuffer(int capacity) {
        buffer = (T[]) new Object[capacity];
        tail = 0;
        size = capacity;
        lock = new ReentrantReadWriteLock();
        notEmpty = lock.writeLock().newCondition();
    }

    /**
     * 添加元素到环形缓冲区
     * 在缓冲区满时会覆盖最早数据。
     */
    public void add(T item) {
        lock.writeLock().lock();
        try {
            buffer[tail] = item;
            tail = (tail + 1) % buffer.length;
            maxIndex.incrementAndGet();
            notEmpty.signalAll();
        } finally {
            lock.writeLock().unlock();
        }
    }

    public ReentrantReadWriteLock.WriteLock getWriteLock(){
        return lock.writeLock();
    }

    /**
     * 获取最大数据index
     */
    public int getMaxIndex(){
        return maxIndex.get();
    }

    /**
     * 获取当前缓冲区大小
     */
    public int size() {
        lock.readLock().lock();
        try {
            return size;
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 根据索引获取元素
     * @param index 索引
     * @return 返回指定索引的元素
     * @throws IndexOutOfBoundsException 如果索引无效
     */
    public T get(int index) {
        lock.readLock().lock();
        try {
            if (index < 0) {
                throw new IndexOutOfBoundsException("Index: " + index);
            }
            return buffer[index % buffer.length];
        } finally {
            lock.readLock().unlock();
        }
    }

    public Condition getCondition() {
        return notEmpty;
    }
}
